using ICSharpCode.SharpZipLib.GZip;
using SDK.Scripts.Utils;
using System;
using System.IO;

namespace SDK.Scripts.Network
{
	public class TCPClict
	{
		public delegate void NetConnectEventHandler(bool ret);

		public delegate void NetDisEventHandler();

		public delegate void NetRecvDataEventHandler(NetMsg msg);

		private byte[] _bufferRecv = new byte[69852];

		private byte[] _bufferSend = new byte[69852];

		private int _bufRecv_len;

		private int _bufSend_len;

		private string _ip = string.Empty;

		private int _port;

		private bool _isConnSvr;

		private bool _isDestroy;

		private static readonly object _locker = new object();

		private UDSocket _udsocket;

		public bool IsConnected
		{
			get
			{
				if (_udsocket != null)
				{
					return _udsocket.IsConnected;
				}
				return false;
			}
		}

		public static event NetConnectEventHandler NetConnEvent;

		public static event NetDisEventHandler NetDisEvent;

		public static event NetRecvDataEventHandler NetDataRecv;

		private TCPClict()
		{
		}

		public TCPClict(string ip, int port)
		{
			_isConnSvr = true;
			ReLacation(ip, port);
		}

		public void ReLacation(string ip = "", int port = 0)
		{
			_ip = ip;
			_port = port;
		}

		private void Reset()
		{
			lock (_locker)
			{
				_bufferRecv = new byte[69852];
				_bufferSend = new byte[69852];
				_bufRecv_len = 0;
				_bufSend_len = 0;
			}
		}

		public void Connect()
		{
			Close();
			UDSocket.ConnectServer += OnConnectSuccess;
			UDSocket.ConnectError += OnConnectError;
			UDSocket.DisConnectServer += OnDisConnect;
			StartConn();
		}

		private void StartConn()
		{
			lock (_locker)
			{
				if (_udsocket == null)
				{
					_udsocket = new UDSocket();
				}
				if (!_udsocket.Connect(_ip, _port))
				{
					OnConnectError(null);
				}
			}
		}

		public void Close(bool isUp = true, int ret = 0)
		{
			lock (_locker)
			{
				if (_udsocket == null)
				{
					UDSocket.NetDataRecv -= OnRecvMessage;
					UDSocket.ConnectServer -= OnConnectSuccess;
					UDSocket.ConnectError -= OnConnectError;
					UDSocket.DisConnectServer -= OnDisConnect;
					if (isUp)
					{
						SendMessage();
					}
					Reset();
					_udsocket.Close();
					_udsocket = null;
					if (!isUp)
					{
						OnDisConnect(null);
					}
				}
			}
		}

		private void OnConnectSuccess(object sender)
		{
			UDSocket.NetDataRecv += OnRecvMessage;
			if (TCPClict.NetConnEvent != null)
			{
				TCPClict.NetConnEvent(ret: true);
			}
		}

		private void OnConnectError(object sender)
		{
			UDSocket.NetDataRecv -= OnRecvMessage;
			if (TCPClict.NetConnEvent != null)
			{
				TCPClict.NetConnEvent(ret: false);
			}
		}

		private void OnDisConnect(object sender)
		{
			if (TCPClict.NetDisEvent != null)
			{
				TCPClict.NetDisEvent();
			}
		}

		public int SendMsg(int reqID, int cmdID, int option, byte[] msg, int connCmdID, int serverId, int svrType)
		{
			ProxyMsg proxyMsg = null;
			if (svrType != -1)
			{
				proxyMsg = new ProxyMsg();
				proxyMsg.mLen = msg.Length + 16 + 16;
				proxyMsg.mType = 1;
				proxyMsg.mOption = (byte)option;
				proxyMsg.type = (byte)svrType;
				proxyMsg.serverid = serverId;
				proxyMsg.mCmd = (byte)connCmdID;
				proxyMsg.mSeq = reqID;
			}
			MsgHead msgHead = new MsgHead();
			msgHead.mLen = msg.Length + 16;
			msgHead.mType = 1;
			msgHead.mOption = (byte)option;
			msgHead.mReserve = 0;
			msgHead.mCmd = cmdID;
			msgHead.mSeq = reqID;
			NetMsg netMsg = new NetMsg();
			netMsg.msgProxy = proxyMsg;
			netMsg.msgHead = msgHead;
			netMsg.msgBody = msg;
			byte[] bytes = null;
			if (netMsg.ObjectToBytes(ref bytes))
			{
				return CacheSendBuffer(bytes, bytes.Length);
			}
			Debuger.LogError("SendMsg faild!");
			return 0;
		}

		public int SendMsg(int reqID, int cmdID, int option, byte[] msg)
		{
			return SendMsg(reqID, cmdID, option, msg, 0, -1, -1);
		}

		private void OnRecvMessage(object sender, byte[] msg, int len)
		{
			lock (_locker)
			{
				if (_bufRecv_len + len > 69852)
				{
					ParseMessage();
				}
				Array.Copy(msg, 0, _bufferRecv, _bufRecv_len, len);
				_bufRecv_len += len;
			}
		}

		private bool ParseMessage()
		{
			lock (_locker)
			{
				Common.SafeCall(delegate
				{
					if (_bufRecv_len > 0)
					{
						int offset = 0;
						int num = 0;
						bool flag = true;
						int ret = 1;
						while (flag)
						{
							if (offset < _bufRecv_len)
							{
								NetMsg netMsg = new NetMsg();
								if (!netMsg.BytesToObject(_isConnSvr, _bufferRecv, ref offset, _bufRecv_len - offset, out ret))
								{
									flag = false;
									if (ret == -1)
									{
										Close(isUp: false, -2);
									}
									break;
								}
								if (((netMsg.msgHead.mOption >> 2) & 1) == 1)
								{
									netMsg.msgBody = UnZip(netMsg.msgBody);
								}
								num = offset;
								Common.SafeCall(delegate
								{
									if (TCPClict.NetDataRecv != null)
									{
										TCPClict.NetDataRecv(netMsg);
									}
								});
							}
							else
							{
								flag = false;
							}
						}
						if (_bufRecv_len < num)
						{
							Close(isUp: false, -2);
						}
						else if (num > 0)
						{
							Array.Copy(_bufferRecv, num, _bufferRecv, 0, _bufRecv_len - num);
							_bufRecv_len -= num;
							Array.Clear(_bufferRecv, _bufRecv_len, _bufferRecv.Length - _bufRecv_len);
						}
					}
				}, delegate
				{
					Close(isUp: false, -2);
				});
				return true;
			}
		}

		private byte[] UnZip(byte[] source)
		{
			MemoryStream memoryStream = new MemoryStream();
			try
			{
				MemoryStream baseInputStream = new MemoryStream(source);
				using (GZipInputStream gZipInputStream = new GZipInputStream(baseInputStream))
				{
					int num = 69852;
					byte[] buffer = new byte[num];
					while (num > 0)
					{
						num = gZipInputStream.Read(buffer, 0, num);
						memoryStream.Write(buffer, 0, num);
					}
					gZipInputStream.Close();
				}
			}
			catch (Exception ex)
			{
				Debuger.LogError("unzip error : " + ex.Message);
			}
			finally
			{
			}
			return memoryStream.ToArray();
		}

		private int CacheSendBuffer(byte[] bytes, int len)
		{
			lock (_locker)
			{
				if (_udsocket != null)
				{
					if (_bufSend_len + len > 69852)
					{
						return -1;
					}
					Array.Copy(bytes, 0, _bufferSend, _bufSend_len, len);
					_bufSend_len += len;
					return bytes.Length;
				}
			}
			return -1;
		}

		private int SendMessage()
		{
			lock (_locker)
			{
				if (_udsocket != null && _udsocket.IsConnected)
				{
					if (_bufSend_len > 0)
					{
						byte[] array = new byte[_bufSend_len];
						Array.Copy(_bufferSend, 0, array, 0, _bufSend_len);
						if (_udsocket.SendMsg(array, _bufSend_len))
						{
							Array.Clear(_bufferSend, 0, _bufSend_len);
							_bufSend_len = 0;
						}
						else if (!_udsocket.IsConnected)
						{
							Array.Clear(_bufferSend, 0, _bufSend_len);
							_bufSend_len = 0;
						}
					}
					return 1;
				}
				return -1;
			}
		}
	}
}
